#include "form_plot_dlg.h"
#include "ui_form_plot_dlg.h"

// add necessary includes here
#include "ui/share/qcustomplot.h"

#define DF_TEMP_CH_SIZE         8

#define DF_AXIS_X_TEMP_DEF      60
#define DF_AXIS_Y_TEMP_DEF      120
#define DF_AXIS_X_FLUO_DEF      40
#define DF_AXIS_Y_FLUO_DEF      100
#define DF_AXIS_X_MELT_MIN      55.0
#define DF_AXIS_X_MELT_MAX      95.0

#define DF_AXIS_ROUND         10
#define DF_AXIS_ROUND_2       1000

/*
 * Function:    FormPlotDlg
 * Description: The default constructor
 * Paramer:     void
 * Return:
 */
FormPlotDlg::FormPlotDlg(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FormPlotDlg)
{
    ui->setupUi(this);

    // After constructing object
    this->_initialze();

    // Initialize control's UI
    this->_initUi();
}

/*
 * Function:    ~FormPlotDlg
 * Description: The default destructor
 * Paramer:     void
 * Return:
 */
FormPlotDlg::~FormPlotDlg()
{
    qDebug() << Q_FUNC_INFO;
    delete ui;

    if(m_pCustomPlot) {
        m_pCustomPlot->clearGraphs();
        delete m_pCustomPlot;
        m_pCustomPlot = nullptr;
    }
}

/*
 * Function:    selectChartType
 * Description: Select chart type and initialize style
 * Paramer:     int nChartType - chart type (temperature/fluorescence/pcr/melting)
 * Return:      void
 */
void FormPlotDlg::selectChartType(int nChartType)
{
    qDebug() << Q_FUNC_INFO << nChartType;
    m_nChartType = nChartType;

    switch (nChartType) {
    case E_CT_TEMP:
    {
        m_dAxisMinX = 0;
        m_dAxisMaxX = DF_AXIS_X_TEMP_DEF;
        m_dAxisMinY = 0;
        m_dAxisMaxY = DF_AXIS_Y_TEMP_DEF;

        m_pCustomPlot->xAxis->setLabel(QString("%1 (%2)").arg(tr("Time")).arg(tr("sec")));
        m_pCustomPlot->yAxis->setLabel(QString("%1 (%2)").arg(tr("Heat")).arg(tr("°C")));
        m_pCustomPlot->xAxis->setNumberFormat("%d");
        m_pCustomPlot->xAxis->setRange((int)m_dAxisMinX, (int)m_dAxisMaxX);
        m_pCustomPlot->yAxis->setRange((int)m_dAxisMinY, (int)m_dAxisMaxY);

        m_pCustomPlot->legend->setMargins(QMargins(50,10,0,10));
        m_pCustomPlot->legend->setFont(QFont("Arial", 8, 5));
        m_pCustomPlot->legend->setSelectedFont(QFont("Arial", 8));
        m_pCustomPlot->legend->setSelectableParts(QCPLegend::spItems);
        m_pCustomPlot->legend->setVisible(true);
        m_pCustomPlot->legend->setFillOrder(QCPLayoutGrid::foColumnsFirst);
        m_pCustomPlot->legend->setWrap(DEF_T1C_LED_COUNT);
        m_pCustomPlot->legend->setBorderPen(Qt::NoPen);
        m_pCustomPlot->plotLayout()->addElement(1, 0, m_pCustomPlot->legend);
        m_pCustomPlot->plotLayout()->setRowStretchFactor(1, 0.001);

        for(int i=0; i<DEF_T1C_LED_COUNT; i++) {
            QPen pen;
            pen.setWidth(1);

            switch (i % 8) {
            case 0: { pen.setColor(QColor(255, 0, 0)); break; }
            case 1: { pen.setColor(QColor(0, 255, 0)); break; }
            case 2: { pen.setColor(QColor(72, 118, 255)); break; }
            case 3: { pen.setColor(QColor(255, 0, 255)); break; }
            case 4: { pen.setColor(QColor(0, 255, 255)); break; }
            case 5: { pen.setColor(QColor(184, 184, 0)); break; }
            case 6: { pen.setColor(QColor(137, 137, 137)); break; }
            case 7: { pen.setColor(QColor(255, 165, 0)); break; }
            default:break;
            }

            m_pCustomPlot->addGraph();
            m_pCustomPlot->graph(i)->setName(QString("CH%1").arg(i+1));
            m_pCustomPlot->graph(i)->setPen(pen);
        }

        ui->pushButton_LegendControl->setVisible(false);
        break;
    }
    case E_CT_FLUO:
    case E_CT_FLUO_EX:
    case E_CT_MELT:
    case E_CT_MELT_EX:
    {
        m_dAxisMinX = 0;
        m_dAxisMaxX = DF_AXIS_X_FLUO_DEF;
        m_dAxisMinY = 0;
        m_dAxisMaxY = DF_AXIS_Y_FLUO_DEF;

        int nLineCnt = DEF_T1C_HOLE_COUNT * DEF_T1C_LED_COUNT;
        QString sAxisTitleX = "";
        QString sAxisTitleY = "";

        if(E_CT_FLUO == nChartType) {
            m_pCustomPlot->xAxis->setNumberFormat("%d");

            sAxisTitleX = QString("%1 (%2)").arg(tr("Cycles")).arg(tr("pcs"));
            sAxisTitleY = QString("%1 (%2)").arg(tr("Fluorescence")).arg(tr("dR"));
        }
        else if(E_CT_FLUO_EX == nChartType) {
            m_pCustomPlot->xAxis->setNumberFormat("%d");

            nLineCnt += DEF_T1C_LED_COUNT;

            sAxisTitleX = QString("%1 (%2)").arg(tr("Cycles")).arg(tr("pcs"));
            sAxisTitleY = QString("%1").arg(tr("RFU"));
        }
        else if(E_CT_MELT == nChartType) {
            m_dAxisMinX = DF_AXIS_X_MELT_MIN;
            m_dAxisMaxX = DF_AXIS_X_MELT_MAX;

            m_pCustomPlot->xAxis->setNumberFormat("%.1f");

            sAxisTitleX = QString("%1 (%2)").arg(tr("Temperature")).arg(tr("°C"));
            sAxisTitleY = QString("%1 (%2)").arg(tr("Fluorescence")).arg(tr("dR"));
        }
        else if(E_CT_MELT_EX == nChartType) {
            m_dAxisMinX = DF_AXIS_X_MELT_MIN;
            m_dAxisMaxX = DF_AXIS_X_MELT_MAX;
            m_dAxisMaxY = DF_AXIS_ROUND_2;

            m_pCustomPlot->xAxis->setNumberFormat("%.1f");

            nLineCnt += 4;

            sAxisTitleX = QString("%1 (%2)").arg(tr("Temperature")).arg(tr("°C"));
            sAxisTitleY = QString("%1").arg(tr("-d(RFU)/dT"));
        }

        m_pCustomPlot->xAxis->setLabel(sAxisTitleX);
        m_pCustomPlot->yAxis->setLabel(sAxisTitleY);

        m_pCustomPlot->xAxis->setRange((int)m_dAxisMinX, (int)m_dAxisMaxX);
        m_pCustomPlot->yAxis->setRange((int)m_dAxisMinY, (int)m_dAxisMaxY);

        for(int i=0; i<nLineCnt; i++) {
            m_pCustomPlot->addGraph();

            QPen pen;
            pen.setWidth(1);

            switch (i % 8) {
            case 0: { pen.setColor(QColor(255, 0, 0)); break; }
            case 1: { pen.setColor(QColor(0, 255, 0)); break; }
            case 2: { pen.setColor(QColor(72, 118, 255)); break; }
            case 3: { pen.setColor(QColor(255, 0, 255)); break; }
            case 4: { pen.setColor(QColor(0, 255, 255)); break; }
            case 5: { pen.setColor(QColor(184, 184, 0)); break; }
            case 6: { pen.setColor(QColor(137, 137, 137)); break; }
            case 7: { pen.setColor(QColor(255, 165, 0)); break; }
            default:break;
            }

            m_pCustomPlot->graph(i)->setPen(pen);
        }

        ui->pushButton_LegendControl->setVisible(true);
        break;
    }
    default:
        break;
    }
}

/*
 * Function:    clearChartData
 * Description: Clear the chart data (melting)
 * Paramer:     double dAxisMinX - minimum axis value
 *              double dAxisMaxX - maximum axis value
 * Return:      void
 */
void FormPlotDlg::clearChartData(int nChartType, double dAxisMinX, double dAxisMaxX)
{
    qDebug() << Q_FUNC_INFO << nChartType << dAxisMinX << dAxisMaxX;

    switch (nChartType) {
    case E_CT_TEMP:
        m_dAxisMinX = 0;
        m_dAxisMaxX = DF_AXIS_X_TEMP_DEF;
        m_dAxisMinY = 0;
        m_dAxisMaxY = DF_AXIS_Y_TEMP_DEF;
        break;
    case E_CT_FLUO:
    case E_CT_FLUO_EX:
        m_dAxisMinX = 0;
        m_dAxisMaxX = DF_AXIS_X_FLUO_DEF;
        m_dAxisMinY = 0;
        m_dAxisMaxY = DF_AXIS_Y_FLUO_DEF;
        break;
    case E_CT_MELT:
    case E_CT_MELT_EX:
        m_dAxisMinX = DF_AXIS_X_MELT_MIN;
        m_dAxisMaxX = DF_AXIS_X_MELT_MAX;
        m_dAxisMinY = 0;
        m_dAxisMaxY = DF_AXIS_ROUND_2;
        break;
    default:
        return;
    }

    if(0 < dAxisMinX && dAxisMinX < dAxisMaxX) {
        m_dAxisMinX = dAxisMinX;
        m_dAxisMaxX = dAxisMaxX;
    }

    m_pCustomPlot->xAxis->setRange((int)m_dAxisMinX, (int)m_dAxisMaxX);
    m_pCustomPlot->yAxis->setRange((int)m_dAxisMinY, (int)m_dAxisMaxY);

    // Set a empty vector for graph
    for(int i=0; i<m_pCustomPlot->graphCount(); i++) {
        m_pCustomPlot->graph(i)->setData(QVector<double>(), QVector<double>());
    }

    m_pCustomPlot->replot();
}

/*
 * Function:    getChartData
 * Description: Get the chart data
 * Paramer:     int nChartType - chart type (temperature/fluorescence/pcr/melting)
 *              QMap<unsigned int, QVector<QPointF>> &mapValue - chart data
 * Return:      int - the size of curves
 */
int FormPlotDlg::getChartData(int nChartType, QMap<unsigned int, QVector<QPointF>> &mapValue)
{
    mapValue.clear();
    int nCurveCnt = 0;
    int nCurveTotal = 0;

    switch (nChartType) {
    case E_CT_TEMP:
        nCurveTotal = DEF_T1C_LED_COUNT;
        break;
    case E_CT_FLUO:
    case E_CT_MELT:
        nCurveTotal = DEF_T1C_HOLE_COUNT * DEF_T1C_LED_COUNT;
        break;
    case E_CT_FLUO_EX:
    case E_CT_MELT_EX:
        nCurveTotal = DEF_T1C_HOLE_COUNT * DEF_T1C_LED_COUNT;
        break;
    default:
        return 0;
    }

    if(nCurveTotal == m_pCustomPlot->graphCount()) {
        for(int i=0; i<nCurveTotal; i++) {
            QVector<QPointF> vecCurve;
            QCPDataContainer<QCPGraphData> *pContainer = m_pCustomPlot->graph(i)->data().data();
            QCPDataContainer<QCPGraphData>::iterator it = pContainer->begin();
            for(; it != pContainer->end(); ++it) {
                vecCurve << QPointF(it->key, it->value);
            }
            mapValue[i] = vecCurve;

            if(0 < vecCurve.size()) nCurveCnt++;
        }
    }

    qDebug() << Q_FUNC_INFO << nChartType << nCurveCnt;
    return nCurveCnt;
}

/*
 * Function:    setChartData
 * Description: Set the chart data by data vector
 * Paramer:     int nLineIdx - the curve index
 *              QMap<unsigned int, QVector<QPointF>> &mapValue - the voctor of curve
 *              bool bUpdateRange - update range or not
 * Return:      void
 */
void FormPlotDlg::setChartData(int nLineIdx, QMap<unsigned int, QVector<QPointF>> &mapValue, bool bUpdateRange)
{
    if(m_pCustomPlot->graph(nLineIdx)) {
        QVector<double> vecKey;
        QVector<double> vecValue;

        if(0 <= nLineIdx && (int)mapValue[nLineIdx].size()) {
            for(int j=0; j<mapValue[nLineIdx].size(); j++) {
                double dX = mapValue[nLineIdx][j].x();
                double dY = mapValue[nLineIdx][j].y();

                vecKey << dX;
                vecValue << dY;

                if(m_dAxisMinX > dX) {
                    m_dAxisMinX = dX;
                }
                else if(m_dAxisMaxX < dX) {
                    m_dAxisMaxX = dX;
                }

                if(m_dAxisMinY > dY) {
                    m_dAxisMinY = dY;
                }
                else if(m_dAxisMaxY < dY) {
                    m_dAxisMaxY = dY;
                }
            }
        }

        m_pCustomPlot->graph(nLineIdx)->setData(vecKey, vecValue);
        m_pCustomPlot->graph(nLineIdx)->setVisible(true);

        if(bUpdateRange) {
            m_dAxisMinY = (int)m_dAxisMinY - (10 + (int)m_dAxisMinY % 10);
            m_dAxisMaxY = (int)m_dAxisMaxY + (DF_AXIS_ROUND_2 - (int)m_dAxisMaxY % DF_AXIS_ROUND_2);

            m_pCustomPlot->xAxis->setRange((int)m_dAxisMinX, (int)m_dAxisMaxX);
            m_pCustomPlot->yAxis->setRange((int)m_dAxisMinY, (int)m_dAxisMaxY);
        }
    }
}

/*
 * Function:    updateChartRange
 * Description: Update the range of chart
 * Paramer:     int nChartType - chart type (temperature/fluorescence/pcr/melting)
 * Return:      void
 */
void FormPlotDlg::updateChartRange(int nChartType)
{
    int nAxisRoundMinX = 0;
    int nAxisRoundMaxX = 0;
    int nAxisRoundMinY = 0;
    int nAxisRoundMaxY = 0;

    switch (nChartType) {
    case E_CT_TEMP:
        nAxisRoundMaxX = DF_AXIS_X_TEMP_DEF;
        nAxisRoundMaxY = DF_AXIS_ROUND;
        break;
    case E_CT_FLUO:
        nAxisRoundMinY = DF_AXIS_ROUND;
        nAxisRoundMaxY = DF_AXIS_ROUND_2;
        break;
    case E_CT_FLUO_EX:
        nAxisRoundMinY = DF_AXIS_ROUND;
        nAxisRoundMaxY = DF_AXIS_ROUND;
        break;
    case E_CT_MELT:
        break;
    case E_CT_MELT_EX:
        break;
    default:
        break;
    }

    for(int i=0; i<m_pCustomPlot->graphCount(); i++) {
        QCPDataContainer<QCPGraphData> *pContainer = m_pCustomPlot->graph(i)->data().data();
        QCPDataContainer<QCPGraphData>::iterator it = pContainer->begin();
        for(; it != pContainer->end(); ++it) {
            double dX = it->key;
            double dY = it->value;

            if(m_dAxisMinX > dX) {
                m_dAxisMinX = dX;
                if(0 < nAxisRoundMinX)
                    m_dAxisMinX = (int)m_dAxisMinX - (nAxisRoundMinX + (int)m_dAxisMinX % nAxisRoundMinX);
            }
            else if(m_dAxisMaxX < dX) {
                m_dAxisMaxX = dX;
                if(0 < nAxisRoundMaxX)
                    m_dAxisMaxX = (int)m_dAxisMaxX + (nAxisRoundMaxX - (int)m_dAxisMaxX % nAxisRoundMaxX);
            }

            if(m_dAxisMinY > dY) {
                m_dAxisMinY = dY;
                if(0 < nAxisRoundMinY)
                    m_dAxisMinY = (int)m_dAxisMinY - (nAxisRoundMinY + (int)m_dAxisMinY % nAxisRoundMinY);
            }
            else if(m_dAxisMaxY < dY) {
                m_dAxisMaxY = dY;
                if(0 < nAxisRoundMaxY)
                    m_dAxisMaxY = (int)m_dAxisMaxY + (nAxisRoundMaxY - (int)m_dAxisMaxY % nAxisRoundMaxY);
            }
        }
    }

    m_pCustomPlot->xAxis->setRange((int)m_dAxisMinX, (int)m_dAxisMaxX);
    m_pCustomPlot->yAxis->setRange((int)m_dAxisMinY, (int)m_dAxisMaxY);

    m_pCustomPlot->replot();

    qDebug() << Q_FUNC_INFO << nChartType << m_pCustomPlot->graphCount() << m_dAxisMinX << m_dAxisMaxX << m_dAxisMinY << m_dAxisMaxY;
}

/*
 * Function:    addChartData
 * Description: Attach data into the chart
 * Paramer:     int nChartType - chart type
 *              int nLineIdx - index of lines
 *              float fValue - data value
 *              bool bUpdateRange - update chart range
 * Return:      void
 */
void FormPlotDlg::addChartData(int nChartType, int nLineIdx, float fValue)
{
    qDebug() << Q_FUNC_INFO << "======U" << nChartType << nLineIdx << fValue;

    if(E_CT_TEMP == m_nChartType) {
        if(DF_TEMP_CH_SIZE > nLineIdx && m_pCustomPlot->graph(nLineIdx)) {
            // Add a point into curve
            int nCycleCnt = m_pCustomPlot->graph(nLineIdx)->dataCount();
            if(0 == nCycleCnt) {
                m_pCustomPlot->graph(nLineIdx)->addData(0, fValue);
                m_pCustomPlot->graph(nLineIdx)->addData(1, fValue);
            }
            else {
                m_pCustomPlot->graph(nLineIdx)->addData(nCycleCnt, fValue);
            }
        }
    }
}

/*
 * Function:    addChartData
 * Description: Attach data into the chart
 * Paramer:     int nType - chart type
 *              int nLineIdx - index of lines
 *              int nCycleIdx - the index of PCR cycles
 *              float fValue - data value
 *              float fAxisMinX - the minimum of axis value
 * Return:      void
 */
void FormPlotDlg::addChartData(int nChartType, int nLineIdx, int nCycleIdx, float fValue, float fAxisMinX , float fAxisMaxX, float fAxisStep)
{
//    qDebug() << Q_FUNC_INFO << "======I" << nChartType << nLineIdx << nCycleIdx << QString::number(fValue, 'f', 0 ) << fAxisMinX << fAxisMaxX << fAxisStep;

    if(E_CT_FLUO == nChartType) {
        if(0 <= nCycleIdx && DEF_T1C_HOLE_COUNT * DEF_T1C_LED_COUNT > nLineIdx) {
            // Add a point into curve
            if(0 == nCycleIdx) {
                m_pCustomPlot->graph(nLineIdx)->addData(0, fValue);
                m_pCustomPlot->graph(nLineIdx)->addData(1, fValue);
            }
            else {
                m_pCustomPlot->graph(nLineIdx)->addData(nCycleIdx + 1, fValue);
            }
        }
    }
    else if(E_CT_MELT == nChartType) {
        if(0 <= nCycleIdx && DEF_T1C_HOLE_COUNT * DEF_T1C_LED_COUNT > nLineIdx) {
            float fX = fAxisMinX + nCycleIdx * fAxisStep;
            if(fAxisMaxX >= fX) {
                // Add a point into curve
                m_pCustomPlot->graph(nLineIdx)->addData(nCycleIdx, fValue);
            }
        }
    }
}

void FormPlotDlg::on_pushButton_Move_clicked(bool checked)
{
    if(checked) {
        m_pCustomPlot->setInteractions(m_pCustomPlot->interactions() | QCP::iRangeDrag);
        m_pCustomPlot->setSelectionRectMode(QCP::SelectionRectMode::srmNone);
        ui->pushButton_Move->setText("☩");
    }
    else {
        m_pCustomPlot->setInteractions(m_pCustomPlot->interactions() & ~QCP::iRangeDrag);
        m_pCustomPlot->setSelectionRectMode(QCP::SelectionRectMode::srmZoom);
        ui->pushButton_Move->setText("⊕");
    }
}

void FormPlotDlg::on_pushButton_Reset_clicked()
{
    m_pCustomPlot->xAxis->setRange((int)m_dAxisMinX, (int)m_dAxisMaxX);
    m_pCustomPlot->yAxis->setRange((int)m_dAxisMinY, (int)m_dAxisMaxY);

    m_pCustomPlot->replot();
}

void FormPlotDlg::on_pushButton_LegendControl_clicked()
{
    QStringList lstAxisRange;
    lstAxisRange << QString::number(m_dAxisMinY, 'f', 0) << QString::number(m_dAxisMaxY, 'f', 0);

    // Set lines status (show/hide)
    emit signalShowLegendControl(m_nChartType, E_CA_AXIS_RANGE, lstAxisRange);
}

/*
* Function:		slotRespondInfoFromDlg
* Description:	Get the reply message from the child window
* Paramer:		int nReplyType - the reply type
*               int nChartAttribute - chart attribute(axis range / curve status)
*               int nLedFlag - LED type flag
*               QStringList lstContent - operation content?
* Return:		void
*/
void FormPlotDlg::slotRespondInfoFromDlg(int nChartType, int nChartAttribute, int nLedFlag, QStringList lstContent)
{
    qDebug() << Q_FUNC_INFO << nChartType <<  nChartAttribute << lstContent.size() << nLedFlag << m_pCustomPlot->graphCount();

    if(m_nChartType != nChartType) return;

    switch (nChartAttribute) {
    case E_CA_AXIS_RANGE:
        if(2 == lstContent.size()) {
            m_dAxisMinY = lstContent.at(0).toDouble();
            m_dAxisMaxY = lstContent.at(1).toDouble();

            m_pCustomPlot->yAxis->setRange((int)m_dAxisMinY, (int)m_dAxisMaxY);
            m_pCustomPlot->replot();
        }
        break;
    case E_CA_CURVE_STATE:
        m_dAxisMinX = 9999999;
        m_dAxisMaxX = 0;
        m_dAxisMinY = 9999999;
        m_dAxisMaxY = 0;

        if(DEF_T1C_HOLE_COUNT * DEF_T1C_LED_COUNT <= m_pCustomPlot->graphCount()) {
            bool bAllHide = true;

            for(int i=0; i<DEF_T1C_HOLE_COUNT; i++) {
                int nHoleLedVal = lstContent.at(i).toInt();

                for(int j=0; j<DEF_T1C_LED_COUNT; j++) {
                    int nLineIdx = i * DEF_T1C_LED_COUNT + j;
                    bool bVisible = (0 < (nHoleLedVal & (0x1 << j))) ? true : false;

                    m_pCustomPlot->graph(nLineIdx)->setVisible(bVisible);

                    if(bVisible) {
                        bAllHide = false;

                        QCPDataContainer<QCPGraphData> *pContainer = m_pCustomPlot->graph(nLineIdx)->data().data();
                        QCPDataContainer<QCPGraphData>::iterator it = pContainer->begin();
                        for(; it != pContainer->end(); ++it) {
                            double dX = it->key;
                            double dY = it->value;

                            if(m_dAxisMinX > dX) {
                                m_dAxisMinX = dX;
                            }
                            else if(m_dAxisMaxX < dX) {
                                m_dAxisMaxX = dX;
                            }

                            if(m_dAxisMinY > dY) {
                                m_dAxisMinY = dY;
                                m_dAxisMinY = (int)m_dAxisMinY - (10 + (int)m_dAxisMinY % 10);
                            }
                            else if(m_dAxisMaxY < dY) {
                                m_dAxisMaxY = dY;
                                m_dAxisMaxY = (int)m_dAxisMaxY + (10 - (int)m_dAxisMaxY % 10);
                            }

                        }
                    }
                }
            }

            if(E_CT_FLUO_EX == nChartType) {
                if(DEF_T1C_HOLE_COUNT * DEF_T1C_LED_COUNT + DEF_T1C_LED_COUNT == m_pCustomPlot->graphCount()) {
                    for(int i=0; i<DEF_T1C_LED_COUNT; i++) {
                        bool bVisible = (0 < (nLedFlag & (0x1 << i))) ? true : false;
                        m_pCustomPlot->graph(DEF_T1C_HOLE_COUNT * DEF_T1C_LED_COUNT + i)->setVisible(bVisible);

                        if(bVisible) {
                            QCPDataContainer<QCPGraphData> *pContainer = m_pCustomPlot->graph(DEF_T1C_HOLE_COUNT * DEF_T1C_LED_COUNT + i)->data().data();
                            QCPDataContainer<QCPGraphData>::iterator it = pContainer->begin();
                            for(; it != pContainer->end(); ++it) {
                                double dX = it->key;
                                double dY = it->value;

                                if(m_dAxisMinX > dX) {
                                    m_dAxisMinX = dX;
                                }
                                else if(m_dAxisMaxX < dX) {
                                    m_dAxisMaxX = dX;
                                }

                                if(m_dAxisMinY > dY) {
                                    m_dAxisMinY = dY;
                                    m_dAxisMinY = (int)m_dAxisMinY - (10 + (int)m_dAxisMinY % 10);
                                }
                                else if(m_dAxisMaxY < dY) {
                                    m_dAxisMaxY = dY;
                                    m_dAxisMaxY = (int)m_dAxisMaxY + (10 - (int)m_dAxisMaxY % 10);
                                }

                            }
                        }
                    }

                }
            }

            if(bAllHide) {
                m_dAxisMinX = 0;
                m_dAxisMaxX = 40;
                m_dAxisMinY = 0;
                m_dAxisMaxY = 40000;
            }

            m_pCustomPlot->xAxis->setRange((int)m_dAxisMinX, (int)m_dAxisMaxX);
            m_pCustomPlot->yAxis->setRange((int)m_dAxisMinY, (int)m_dAxisMaxY);

            m_pCustomPlot->replot();
        }

        break;
    default:
        break;
    }
}

void FormPlotDlg::slotSelectionChanged()
{
    // make top and bottom axes be selected synchronously, and handle axis and tick labels as one selectable object:
    if (m_pCustomPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis) || m_pCustomPlot->xAxis->selectedParts().testFlag(QCPAxis::spTickLabels)) {
        m_pCustomPlot->xAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
    }

    // make left and right axes be selected synchronously, and handle axis and tick labels as one selectable object:
    if (m_pCustomPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis) || m_pCustomPlot->yAxis->selectedParts().testFlag(QCPAxis::spTickLabels)) {
        m_pCustomPlot->yAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
    }

    for (int i=0; i<m_pCustomPlot->graphCount(); ++i) {
        QCPGraph *graph = m_pCustomPlot->graph(i);
        QCPPlottableLegendItem *item = m_pCustomPlot->legend->itemWithPlottable(graph);
        if (item->selected() || graph->selected()) {
            item->setSelected(true);
            graph->setSelection(QCPDataSelection(graph->data()->dataRange()));
        }
    }
}

/*
* Function:		changeEvent
* Description:	Triggers an event before it is switch language
* Paramer:		QShowEvent *event - the pointer of "QEvent"
* Return:		void
*/
void FormPlotDlg::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);

    switch (e->type())
    {
    case QEvent::LanguageChange:
    {
        QString sAxisTitleX = "";
        QString sAxisTitleY = "";


        if(E_CT_FLUO == m_nChartType) {
            sAxisTitleX = QString("%1 (%2)").arg(tr("Cycles")).arg(tr("pcs"));
            sAxisTitleY = QString("%1 (%2)").arg(tr("Fluorescence")).arg(tr("dR"));
        }
        else if(E_CT_FLUO_EX == m_nChartType) {
            sAxisTitleX = QString("%1 (%2)").arg(tr("Cycles")).arg(tr("pcs"));
            sAxisTitleY = QString("%1").arg(tr("RFU"));
        }
        else if(E_CT_MELT == m_nChartType) {
            sAxisTitleX = QString("%1 (%2)").arg(tr("Temperature")).arg(tr("°C"));
            sAxisTitleY = QString("%1 (%2)").arg(tr("Fluorescence")).arg(tr("dR"));
        }
        else if(E_CT_MELT_EX == m_nChartType) {
            sAxisTitleX = QString("%1 (%2)").arg(tr("Temperature")).arg(tr("°C"));
            sAxisTitleY = QString("%1").arg(tr("-d(RFU)/dT"));
        }

        m_pCustomPlot->xAxis->setLabel(sAxisTitleX);
        m_pCustomPlot->yAxis->setLabel(sAxisTitleY);

        qDebug() << Q_FUNC_INFO;

        ui->retranslateUi(this);
        break;
    }
    default:
        break;
    }
}

/*
 * Function:    _initialze
 * Description: After constructing object, initialize the object
 * Paramer:     void
 * Return:      void
 */
void FormPlotDlg::_initialze()
{
    qDebug() << Q_FUNC_INFO;

    if(!m_pCustomPlot) {
        m_pCustomPlot = new QCustomPlot(ui->widget_Chart);
        Q_ASSERT(m_pCustomPlot);
    }

    // Signal-slot initialization
    std::vector<bool> vecConnect;
    for(int i=0; i<(int)vecConnect.size(); i++) {
        Q_ASSERT(vecConnect.at(i));
    }
//    vecConnect.push_back(QObject::connect(m_pCustomPlot, SIGNAL(selectionChangedByUser()), this, SLOT(slotSelectionChanged())));
    ui->pushButton_Move->setCheckable(true);
    ui->pushButton_Move->setChecked(false);
}

/*
* Function:		_initUi
* Description:	Init the window style
* Paramer:		void
* Return:		void
*/
void FormPlotDlg::_initUi()
{
    qDebug() << Q_FUNC_INFO;

    // Displays the background image of the window
    QWidget::setAttribute(Qt::WA_StyledBackground);

    SET_STYLE_SHEET(QString(":/%1/share/%2.qss").arg("skin_1").arg(this->objectName()));

    QFont font;
    font.setFamily("Arial");
    font.setPointSize(12);
    font.setBold(false);
    font.setItalic(false);

    m_pCustomPlot->xAxis->setLabelFont(font);
    m_pCustomPlot->yAxis->setLabelFont(font);
    m_pCustomPlot->xAxis->setVisible(true);
    m_pCustomPlot->yAxis->setVisible(true);
    m_pCustomPlot->xAxis->setTicks(true);
    m_pCustomPlot->yAxis->setTicks(true);
    m_pCustomPlot->xAxis->setTickLabels(true);
    m_pCustomPlot->yAxis->setTickLabels(true);
    m_pCustomPlot->xAxis->setTickLengthIn(1);
    m_pCustomPlot->yAxis->setTickLengthIn(1);
    m_pCustomPlot->xAxis->setTickLengthOut(5);
    m_pCustomPlot->yAxis->setTickLengthOut(5);
    m_pCustomPlot->xAxis->setSubTicks(true);
    m_pCustomPlot->yAxis->setSubTicks(true);
    m_pCustomPlot->xAxis->setSubTickLength(2);
    m_pCustomPlot->yAxis->setSubTickLength(2);
    m_pCustomPlot->xAxis->ticker()->setTickCount(10);
    m_pCustomPlot->yAxis->ticker()->setTickCount(10);

    m_pCustomPlot->xAxis->setRange(0, 1);
    m_pCustomPlot->yAxis->setRange(0, 1);

    m_pCustomPlot->xAxis2->setVisible(true);
    m_pCustomPlot->yAxis2->setVisible(true);
    m_pCustomPlot->xAxis2->setTicks(false);
    m_pCustomPlot->yAxis2->setTicks(false);

    m_pCustomPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables);
    m_pCustomPlot->setGeometry(0, 40, this->width()-20, this->height()-20);

    m_pCustomPlot->selectionRect()->setPen(QPen(Qt::black, 1, Qt::DashLine));
    m_pCustomPlot->selectionRect()->setBrush(QBrush(QColor(0, 0, 100, 50)));
    m_pCustomPlot->setSelectionRectMode(QCP::SelectionRectMode::srmZoom);

    ui->widget_Chart->setMinimumSize(700, 400);
    m_pCustomPlot->setMaximumSize(ui->widget_Chart->size());
}
